import { type RefGetGameListQuery } from "@/apis/home_page_constant_types"
import { parseOcrClientCfg } from "@/utils/common"
import ENV from "@/utils/env"
import { CustomError, ErrorCode, ErrorFactory } from "@/utils/error"
import { createLogger } from "@/utils/logger"
import { toast } from "react-toastify"
import Apis from "."
import ApiSignals from "./api_signals"
import ApiUtils from "./api_utils"
import { tokenStore } from "@/utils/cached"
import _ from "lodash"
import cbor from "cbor-js"
import { PayloadFormatter } from "@/utils/format"

const logger = createLogger("ApiFetchers")

const ApiFetchers = {
    async getClientAssets() {
        try {
            const hostname = ENV.dev_mode ? "test.filbet2025.com" : location.hostname
            const brand_name = hostname.split(".")[0] as ApiTypes.BrandName

            const [responseCommon, responseDefault, responseCurrent] = await Promise.all([
                ApiUtils.getFormattedBrandAssets("common"),
                ApiUtils.getFormattedBrandAssets("filbet.com"),
                ApiUtils.getFormattedBrandAssets(hostname),
            ])

            // 預設數據
            const default_banners = responseDefault["home_carousel"]?.imageCarousel ?? []
            const default_game_sections = responseDefault["home_game_sections"]?.gameSections ?? []
            const default_game_categories = responseDefault["home_game_categories"]?.gameMenus ?? []

            // 當前品牌數據key
            const bannersKey: ApiTypes.Fetcher.Result.BrandAssetTypes.AtomKey = `home_carousel_${brand_name}`
            const gameSectionsKey: ApiTypes.Fetcher.Result.BrandAssetTypes.AtomKey = `home_game_sections_${brand_name}`
            const gameCategoriesKey: ApiTypes.Fetcher.Result.BrandAssetTypes.AtomKey = `home_game_categories_${brand_name}`
            // 當前品牌數據
            const home_banners = responseCurrent[bannersKey]?.imageCarousel ?? default_banners ?? []
            const home_game_sections =
                responseCurrent[gameSectionsKey]?.gameSections ?? default_game_sections ?? []
            const home_game_categories =
                responseCurrent[gameCategoriesKey]?.gameMenus ?? default_game_categories ?? []

            // 共用數據
            const brand_logo = Object.fromEntries(
                // @ts-ignore
                (responseCommon?.["brand-logo"] ?? responseCommon?.["brand_logo"])?.imageCarousel
                    ?.filter((it) => it.link.startsWith(brand_name))
                    ?.map((it) => [it.link.split("-").slice(-2).join("-"), it]),
            ) as Partial<
                Record<
                    ApiTypes.Fetcher.Result.BrandAssetTypes.LogoType,
                    ApiTypes.Fetcher.Result.BrandAssetTypes.ImageItem
                >
            >

            return {
                homeBanners: home_banners,
                homeGameSections: home_game_sections,
                homeGameCategories: home_game_categories,
                brandLogo: brand_logo,
            }
        } catch (error) {
            logger.debug("getClientAssets", error)
            return {
                homeBanners: [],
                homeGameSections: [],
                homeGameCategories: [],
                brandLogo: {} as Partial<
                    Record<
                        ApiTypes.Fetcher.Result.BrandAssetTypes.LogoType,
                        ApiTypes.Fetcher.Result.BrandAssetTypes.ImageItem
                    >
                >,
            }
        }
    },
    async getBrandList() {
        type Data = ApiTypes.Fetcher.Util.ExtractDataFromApi<typeof Apis.v1.getBrandList>
        try {
            const response = await Apis.v1.getBrandList()
            return (response.data.data ?? []) as Data
        } catch (error) {
            logger.debug("getBrandList", error)
            return [] as Data
        }
    },
    async getGameList(props?: ApiTypes.Fetcher.Props.getGameList) {
        type Item = ApiTypes.Fetcher.Util.ExtractItemFromListApi<typeof Apis.v1.getGameList>
        type Result = globalThis.ApiTypes.Fetcher.Result.List<Item, typeof props>
        try {
            const response = await Apis.v1.getGameList({
                limit: props?.limit?.toString(),
                // @ts-ignore
                categories: props?.categories,
                // @ts-ignore
                brands: props?.brands,
                cursor: props?.cursor,
            })

            const result: Result = {
                cursor: response.data.data?.cursor ?? null,
                list: response.data.data?.list ?? [],
                total: null,
                hasMore: response.data.data?.hasMore ?? false,
                query: props,
            }

            return result
        } catch (error) {
            logger.debug("getGameList", error)
            return {
                cursor: null,
                list: [],
                total: null,
                hasMore: false,
                query: props,
            } as Result
        }
    },
    async sendOtpPhoneNumber(props: { phoneNumber: string; countryCode?: string }): Promise<{
        id: string
        codeLength: number
        resendAt: number
    } | null> {
        logger.debug("sendOtpPhoneNumber", props)

        const phone = `${props.phoneNumber.match(/9\d+/g)?.[0] ?? ""}`

        const response = await Apis.v1.sendSmsOtp({
            country_code: props.countryCode ?? "63",
            phone: phone,
        })
        logger.debug("sendOtpPhoneNumber", response.data.data)
        return {
            id: response.data.data?.id ?? "",
            codeLength: response.data.data?.codeLength ?? 6,
            resendAt: response.data.data?.resendAt ?? 0,
        }
    },
    async loginWithOtp(props: { otpId: string; otpCode: string }): Promise<void> {
        const response = await Apis.v1.loginWithSmsOtpCode({
            otp_id: props.otpId,
            code: props.otpCode,
        })
        const accessToken = response.data.data
        if (!accessToken) {
            throw ErrorFactory.create(ErrorCode.VALIDATION_ERROR, "loginWithOtp", response.data)
        }
        tokenStore.set({
            accessToken,
        })
    },
    async loginWithPassword(props: {
        countryCode: string
        number: string
        password: string
    }): Promise<void> {
        const response = await Apis.v1.loginWithPassword({
            country_code: props.countryCode,
            phone: props.number,
            password: props.password,
        })
        const accessToken = response.data.data
        if (!accessToken) {
            throw ErrorFactory.create(
                ErrorCode.VALIDATION_ERROR,
                "loginWithPassword",
                response.data,
            )
        }
        tokenStore.set({
            accessToken,
        })
    },

    async logout(): Promise<{
        success: boolean
    } | null> {
        try {
            const response = await Apis.v1.logout()
            return {
                success: !!response.data.status,
            }
        } catch (error) {
            logger.debug("logout", error)
            return null
        }
    },
    async rechargeByWeb(props: { amount: string; channelName: string; redirectUrl: string }) {
        try {
            const response = await Apis.v1.rechargeByWeb({
                amount: props.amount,
                channelName: props.channelName,
                redirectUrl: props.redirectUrl,
            })
            return response.data.data
        } catch (error) {
            logger.debug("rechargeByWeb", error)
            return null
        }
    },
    async getWallet(): Promise<ApiTypes.Fetcher.Result.UserWallet> {
        try {
            const response = await Apis.v1.getWallet()
            return {
                ...response.data.data,
            } as ApiTypes.Fetcher.Result.UserWallet
        } catch (error) {
            logger.debug("getWallet", error)
            return {} as ApiTypes.Fetcher.Result.UserWallet
        }
    },

    async updateEmail(
        data: ApiTypes.Fetcher.Props.UpdateEmail,
    ): Promise<ApiTypes.Fetcher.Result.UpdateEmailResult> {
        try {
            const response = await Apis.v1.changeAccountEmail(data)
            return response.data as ApiTypes.Fetcher.Result.UpdateEmailResult
        } catch (error) {
            logger.debug("updateEmail", error)
            return {} as ApiTypes.Fetcher.Result.UpdateEmailResult
        }
    },
    async updatePassword(
        data: ApiTypes.Fetcher.Props.updatePassword,
    ): Promise<ApiTypes.Fetcher.Result.UpdatePassword> {
        try {
            const response = await Apis.v1.changeLoginPassword(data)
            return response.data.data as ApiTypes.Fetcher.Result.UpdatePassword
        } catch (error) {
            return {} as ApiTypes.Fetcher.Result.UpdatePassword
        }
    },
    async uploadFile(file: File) {
        try {
            const response = await Apis.v1.getUploadRequest({
                contentType: file.type,
                name: file.name,
                size: file.size,
            })

            const responseData = response.data.data
            if (!responseData?.uploadRequest?.url) {
                throw ErrorFactory.create(
                    ErrorCode.FETCH_ERROR,
                    "uploadRequest.url is null",
                    responseData,
                )
            }

            const uploadResponse = await fetch(responseData.uploadRequest.url, {
                method: "PUT",
                body: file,
                headers: {
                    "Content-Type": file.type,
                    "Content-Length": file.size.toString(),
                },
            })

            if (!uploadResponse.ok) {
                throw ErrorFactory.create(
                    ErrorCode.FETCH_ERROR,
                    "uploadResponse.ok is false",
                    uploadResponse,
                )
            }

            return responseData.accessUrl
        } catch (error) {
            logger.debug("getUploadRequest", error)
            return null
        }
    },
    async getGameUrl(name: string): Promise<string | null> {
        const [brand] = name.split("_")
        const v2Brands = [
            //
            "jili",
            "pg",
            "jl",
            "evo",
            "jdb",
            "cq9",
            "pp",
        ]
        if (v2Brands.includes(brand)) {
            try {
                const response = await Apis.v2.getGameUrlWithLaunchToken(name)
                const isPG = brand.trim().toLowerCase() === "pg"
                if (isPG) {
                    const dataUrl = `data:text/html;charset=utf-8,${encodeURIComponent(response)}`
                    return dataUrl.toString() || null
                }
                return response || null
            } catch (error) {
                logger.debug("getGameUrl", error)
                return null
            }
        }
        const response = await Apis.v1.getGameUrl(name)
        return response.data.data || null
    },
    /**
     * 模擬異步獲取配置數據
     * @returns 返回示例頁面的配置數組
     */
    async getSomeConfigAsync() {
        // 定義配置項的類型
        type Config = {
            topic: string // 主題名稱
            key:
                | "login"
                | "atom_and_repository"
                | "framer_motion"
                | "jotai"
                | "form_demo"
                | "easy_form_demo"
                | "styled_components"
                | "auth"
                | "navs" // 路由鍵值
                | "pag"
            deprecated?: boolean // 是否棄用
        }

        // 模擬的配置數據
        const config: Config[] = [
            {
                topic: "Login",
                key: "login",
            },
            {
                topic: "Atom & Repository",
                key: "atom_and_repository",
            },
            {
                topic: "Form demo",
                key: "form_demo",
            },
            {
                topic: "Easy Form demo",
                key: "easy_form_demo",
            },
            {
                topic: "Framer Motion",
                key: "framer_motion",
            },
            {
                topic: "Jotai",
                key: "jotai",
            },
            {
                topic: "Styled Components",
                key: "styled_components",
            },
            {
                topic: "Auth",
                key: "auth",
            },
            {
                topic: "Navs",
                key: "navs",
            },
            {
                topic: "Pag",
                key: "pag",
            },
        ]

        return config
    },
    /**
     * 查询投注记录
     * @returns 投注记录列表
     */
    async getGameBetList(props?: ApiTypes.Fetcher.Props.getBetRecordListProps) {
        const response = await Apis.v1.refGetGameBetList(props)

        const betRecord: BetApiTypes.Fetcher.Response.BetRecord[] = []
        const data = response.data.data?.d || []
        data.map((it) => {
            betRecord.push({
                bet_amount: it.bet_amount ?? "",
                brand_name: it.brand_name,
                currency: it.currency ?? "",
                game_name: it.game_name ?? "",
                game_type: it.game_type ?? "",
                id: it.id ?? 0,
                net_amount: it.net_amount ?? "",
                record_id: it.record_id ?? "",
                round_id: it.round_id,
                settle_time: it.settle_time ?? 0,
                settlement_amount: it.settlement_amount ?? "",
                status: it.status ?? 0,
            })
        })

        const result: BetApiTypes.Fetcher.Response.BetRecordResult = {
            list: betRecord,
            total: response.data.data?.t || 0,
            bt: response.data.data?.bt ?? "",
            wt: response.data.data?.wt ?? "",
        }

        return result
    },
    /**
     * 查询交易记录
     * @returns 记录列表
     */
    async getTransactionRecords(props?: TransactionApiTypes.Fetcher.Request.Params) {
        const response = await Apis.v1.refGetTransactionList(props)
        const data = response.data.data?.data || []
        const total = response.data.data?.t || 0
        const status = response.data.data?.s || 0

        const transRecord: TransactionApiTypes.Fetcher.Response.Record[] = []
        data.map((it) => {
            transRecord.push({
                id: it.id ?? "",
                name: it.remark ?? "",
                timestamp: it.created_at ?? 0,
                amount: it.amount ?? "",
                after_balance: it.after_amount ?? "",
            })
        })
        const result: TransactionApiTypes.Fetcher.Response.Result = {
            list: transRecord,
            total,
            status,
        }
        return result
    },
    /**
     * 查询充值记录
     * @returns 记录列表
     */
    async getFinanceDepositList(props?: TransactionApiTypes.Fetcher.Request.Params) {
        const response = await Apis.v1.refGetFinanceDepositList(props)
        const data = response.data.data?.d || []
        const total = response.data.data?.t || 0
        const status = response.data.data?.s || 0

        const transRecord: TransactionApiTypes.Fetcher.Response.Record[] = []
        data.map((it) => {
            transRecord.push({
                id: it.id ?? "",
                name: it.channel_name ?? "",
                timestamp: it.created_at ?? 0,
                amount: it.amount ?? "",
                status: it.status ?? "",
            })
        })
        const result: TransactionApiTypes.Fetcher.Response.Result = {
            list: transRecord,
            total,
            status,
        }
        return result
    },
    /**
     * 查询提现记录
     * @returns 记录列表
     */
    async getFinanceWithdrawList(props?: TransactionApiTypes.Fetcher.Request.Params) {
        const response = await Apis.v1.refGetFinanceWithdrawList(props)
        const data = response.data.data?.d || []
        const total = response.data.data?.t || 0
        const status = response.data.data?.s || 0

        const transRecord: TransactionApiTypes.Fetcher.Response.Record[] = []
        data.map((it) => {
            transRecord.push({
                id: it.id ?? "",
                name: it.channel_name ?? "",
                timestamp: it.created_at ?? 0,
                amount: it.amount ?? "",
                status: it.status ?? "",
            })
        })
        const result: TransactionApiTypes.Fetcher.Response.Result = {
            list: transRecord,
            total,
            status,
        }
        return result
    },
    /**
     * 查询奖金记录
     * @returns 记录列表
     */
    async getTransactionBonus(props?: TransactionApiTypes.Fetcher.Request.Params) {
        const response = await Apis.v1.refGetTransactionBonus(props)
        const data = response.data.data?.list || []
        const total = response.data.data?.t || 0
        const status = response.data.data?.s || 0

        const transRecord: TransactionApiTypes.Fetcher.Response.Record[] = []
        data.map((it) => {
            transRecord.push({
                id: it.id ?? "",
                name: it.promo_name ?? "",
                timestamp: it.created_at ?? 0,
                amount: it.amount ?? "",
                status: it.status ?? "",
            })
        })
        const result: TransactionApiTypes.Fetcher.Response.Result = {
            list: transRecord,
            total,
            status,
        }
        return result
    },
    async getFinanceAccountList() {
        const response = await Apis.v1.refGetFinanceAccountList()
        const data = response.data.data || []
        const accountList: FinanceAccountApiTypes.Fetcher.Response.record[] = []
        data.map((it) => {
            accountList.push({
                account: it.account ?? "",
                channel_name: it.channel_name ?? "",
                currency: it.currency ?? "",
                first_name: it.first_name ?? "",
                id: it.id ?? "",
                last_name: it.last_name ?? "",
                middle_name: it.middle_name ?? "",
                status: it.status ?? 0,
                uid: it.uid ?? "",
            })
        })
        const result: FinanceAccountApiTypes.Fetcher.Response.Result = {
            list: accountList,
            status: response.data?.status ?? false,
        }
        return result
    },
    async refGetFinanceChannelList(params: FinanceChannelApiTypes.Fetcher.Query.Params) {
        const response = await Apis.v1.refGetFinanceChannelList(params)
        const data = response.data.data || []
        const channelList: FinanceChannelApiTypes.Fetcher.Response.record[] = []
        data.map((it) => {
            channelList.push({
                flag: it.flag ?? 0,
                id: it.id ?? "",
                img: it.img ?? "",
                max_amount: it.max_amount ?? "",
                min_amount: it.min_amount ?? "",
                name: it.name ?? "",
            })
        })
        const result: FinanceChannelApiTypes.Fetcher.Response.Result = {
            data: channelList,
            status: response.data?.status ?? false,
        }
        return result
    },
    async addFavoriteGame(name: string) {
        try {
            return await Apis.v1.addFavoriteGame(name)
        } catch (error) {
            logger.debug("favoritesGame", error)
            return Promise.reject(error)
        }
    },

    async removeFavoriteGame(name: string) {
        try {
            return await Apis.v1.removeFavoriteGame(name)
        } catch (error) {
            logger.debug("unFavoritesGame", error)
            return Promise.reject(error)
        }
    },
    async getFavoriteGameList() {
        try {
            const response = await Apis.v1.getFavoriteGameList()
            return response.data.data
        } catch (error) {
            logger.debug("getFavoritesGame", error)
            return []
        }
    },
    async refGetGameLaunch(props: {
        /** @example "pp_slot_angel_vs_sinner_vs15fghtmultlv" */
        code?: string
    }) {
        try {
            const response = await Apis.v1.refGetGameLaunch(props)
            const [brand] = props.code ? props.code.split("_") : ""
            const isPG = brand.trim().toLowerCase() === "pg"
            let resp = response.data.data || ""
            if (isPG) {
                const dataUrl = `data:text/html;charset=utf-8,${response.data.data}`
                resp = dataUrl.toString() || ""
            }
            logger.debug("refGetGameLaunch success", resp)
            return resp
        } catch (error) {
            logger.debug("refGetGameLaunch err", error)
            if (error instanceof CustomError) {
                return error.toString()
            }
            return String(error)
        }
    },
    async refGetGameFav(props: {
        /**
         * 查询页
         * @format int32
         */
        page?: number
        /**
         * 每页数量
         * @format int32
         */
        page_size?: number
    }) {
        try {
            const response = await Apis.v1.refGetGameFavList(props)
            logger.debug("refGetGameFavList", response.data.data)
            return response.data.data
        } catch (error) {
            if (error instanceof CustomError) {
                toast(error.toString())
            }
            logger.debug("refGetGameFavList", error)
            return {}
        }
    },
    async refInsertGameFav(props: {
        /** @example "0" */
        id?: string
    }) {
        try {
            const response = await Apis.v1.refGetAddGameFav(props)
            return response.data
        } catch (error) {
            logger.debug("getFavoritesGame", error)
            return {}
        }
    },
    async refGetDeleteGameFav(props: {
        /** @example "0" */
        id?: string
    }) {
        try {
            const response = await Apis.v1.refGetDeleteGameFav(props)
            return response.data
        } catch (error) {
            logger.debug("getFavoritesGame", error)
            return {}
        }
    },
    async getRechargeChannelList() {
        try {
            const response = await Apis.v1.getRechargeChannelList()
            return response.data.data ?? {}
        } catch (error) {
            logger.debug("getRechargeChannelList", error)
            return []
        }
    },
    async refUpdateDetail(props: {
        record: {
            email?: string
            phone?: string
            nick_name?: string
            gender?: string
            real_username?: string
            birthday?: string
        }
        otp_id?: string
        code?: string
    }) {
        const response = await Apis.v1.refUpdateDetail(props)
        return response.data.data
    },
    async refGetProfile(): Promise<ApiTypes.Fetcher.Result.UserProfile> {
        const response = await Apis.v1.refGetProfile()
        const data = response.data.data
        const real_username = PayloadFormatter.jsonParse(data?.real_username) as {
            first_name: string
            middle_name: string
            last_name: string
        }

        const output: Required<ApiTypes.Fetcher.Result.UserProfile> = {
            uid: data?.uid ?? "",
            username: data?.username ?? "",
            email: data?.email ?? "",
            email_check_state: data?.email_check_state ?? 0,
            country_code: data?.country_code ?? "",
            phone: data?.phone ?? "",
            phone_check_state: data?.phone_check_state ?? 0,
            avatar: data?.avatar ?? "",
            gender: data?.gender ?? "",
            password: data?.password ?? "",
            oauth_secrets: data?.oauth_secrets ?? "",
            referral_code: data?.referral_code ?? "",
            tags: data?.tags ?? "",
            vip: data?.vip ?? 0,
            parent_uid: data?.parent_uid ?? "",
            parent_name: data?.parent_name ?? "",
            tester: data?.tester ?? 0,
            device_number: data?.device_number ?? "",
            state: data?.state ?? 0,
            note: data?.note ?? "",
            created_at: data?.created_at ?? 0,
            created_ip: data?.created_ip ?? "",
            reg_ip: data?.reg_ip ?? "",
            reg_device: data?.reg_device ?? 0,
            reg_device_no: data?.reg_device_no ?? "",
            last_login_ip: data?.last_login_ip ?? "",
            last_login_at: data?.last_login_at ?? 0,
            last_login_device: data?.last_login_device ?? 0,
            nick_name: data?.nick_name ?? "",
            updated_at: data?.updated_at ?? 0,
            hasLoginPassword: data?.has_login_password ?? false,
            hasEmail: data?.has_email ?? false,
            hasPhoneNumber: data?.has_phone_number ?? false,
            realName: {
                firstName: real_username.first_name ?? "",
                middleName: real_username.middle_name ?? "",
                lastName: real_username.last_name ?? "",
            },
            phoneNumber: {
                number: data?.phone ?? "",
                countryCode: data?.country_code ?? "",
            },
            has_email: data?.has_email ?? false,
            hasEmailVerified: false,
            nickname: data?.nick_name ?? "",
        }

        ApiSignals.dataSiganlProfile.value = {
            ...output,
        }

        return output
    },
    //旧密码修改新密码
    async refUpdatePassword(props: { password: string; new_password: string }) {
        try {
            const response = await Apis.v1.refUpdatePassword(props)
            return response
        } catch (error) {
            logger.debug("refUpdatePassword", error)
            return null
        }
    },
    //重置密码
    async resetPasswordWithOtpCode(props: {
        code?: string
        new_password?: string
        otp_id?: string
    }) {
        try {
            const response = await Apis.v1.resetPasswordWithOtpCode(props)
            return response
        } catch (error) {
            logger.debug("resetPasswordWithOtpCode", error)
            return null
        }
    },
    //旧密码前置验证
    async refAuthPassword(props: { password: string }) {
        try {
            const response = await Apis.v1.refAuthPassword(props)
            return response
        } catch (error) {
            logger.debug("refAuthPassword", error)
            return null
        }
    },
    //短信验证码前置检查
    async refPostAuthSms(props: {
        code: string
        phone: string
        country_code: string
        otp_id: string
    }) {
        try {
            const response = await Apis.v1.refPostAuthSms(props)
            return response
        } catch (error) {
            logger.debug("refPostAuthSms", error)
            return null
        }
    },
    async refPlatformList(props: {
        /**
         * 查询页
         * @format int32
         */
        page?: number
        /**
         * 每页数量
         * @format int32
         */
        page_size?: number
        /**
         * 0所有 1视讯 2捕鱼 3老虎机 5棋牌 7bingo
         * @example "1"
         */
        game_type?: string
        /**
         * 1开启2关闭
         * @example "1"
         */
        state?: string
    }) {
        try {
            const response = await Apis.v1.refGetGamePlatform(props)
            logger.debug("refPlatformList", response.data.data)
            return response.data.data
        } catch (error) {
            logger.debug("refPlatformList", error)
            return null
        }
    },
    //钱包余额
    async refGetFinanceWallet() {
        const response = await Apis.v1.refGetFinanceWallet()
        return response.data.data
    },
    async refGetIndexCache() {
        try {
            const response = await Apis.v1.refGetIndexCache()
            logger.debug("refGetIndexCache", response.data.data)
            return response.data.data
        } catch (error) {
            logger.debug("refGetIndexCache error", error)
            return {}
        }
    },
    async refGetGameList(props: RefGetGameListQuery) {
        try {
            const response = await Apis.v1.refGetGameList(props)
            logger.debug("refGetGameList", response.data.data)
            return response.data.data
        } catch (error) {
            logger.debug("refPlatformList", error)
            return {}
        }
    },
    async refRefreshToken(): Promise<{ status?: boolean | undefined; data?: string | undefined }> {
        const response = await Apis.v1.refreshToken()
        logger.debug("refRefreshToken", response.data.data)
        return { status: response.data?.status, data: response.data?.data }
    },
    async getKyc(): Promise<ApiTypes.Fetcher.Result.KycInfo> {
        const response = await Apis.v1.refGetKyc()
        return {
            ...response.data.data,
            status: (response.data.data?.status ?? "unset") as Kyc.Status,
        } as ApiTypes.Fetcher.Result.KycInfo
    },
    async getKycV2(): Promise<Partial<Kyc.Data.Detail>> {
        const response = await Apis.v1.refGetKyc()
        const data = response.data.data
        if (!data) {
            return {}
        }
        const output: Partial<Kyc.Data.Detail> = {
            uid: data.uid,
            created_at: data.created_at,
            updated_at: data.updated_at,
            country_code: data.country_code,
            phone: data.phone,
            first_name: data.first_name,
            last_name: data.last_name,
            id_type: data.id_type as Kyc.IdType,
            id_number: data.id_number,
            birthday: data.birthday,
            nearest_branch: data.nearest_branch,
            gender: data.gender as Kyc.Gender,
            attachments_face: data.attachments?.face,
            attachments_faceTmpUrl: data.attachments?.faceTmpUrl,
            attachments_idPhoto: data.attachments?.idPhoto,
            attachments_idPhotoTmpUrl: data.attachments?.idPhotoTmpUrl,
            attachments_selfieWithIDPhotoPath: data.attachments?.selfieWithIDPhotoPath,
            extra_details_issuing_authority: data.extra_details?.issuing_authority,
            extra_details_expiry_date: data.extra_details?.expiry_date,
            place_of_birth: data.place_of_birth,
            nationality: data.nationality,
            current_address: data.current_address,
            permanent_address: data.permanent_address,
            nature_of_work: data.nature_of_work,
            source_of_income: data.source_of_income,
            occupation: data.occupation,
            tokens: data.tokens,
            blacklist_status: data.blacklist_status as Kyc.BlacklistStatus,
            issue_message: data.issue?.message,
            issue_msg: data.issue_msg,
            issue_fields: data.issue_fields,
            status: (data.status || "unset") as Kyc.Status,
            comment: data.comment,
            reviewer: data.reviewer,
            review_times: data.review_times,
            ocr_status: data.ocr_status as Kyc.OcrStatus,
            ocr_realName_firstName: data.ocr?.realName?.firstName,
            ocr_realName_middleName: data.ocr?.realName?.middleName,
            ocr_realName_lastName: data.ocr?.realName?.lastName,
            ocr_birthday: data.ocr?.birthday,
            ocr_idType: data.ocr?.idType as Kyc.IdType,
            ocr_idNumber: data.ocr?.idNumber,
            ocr_gender: data.ocr?.gender as Kyc.Gender,
            ocr_attachments_face: data.ocr?.attachments?.face,
            ocr_attachments_idPhoto: data.ocr?.attachments?.idPhoto,
            ocr_extraDetails_confidence_score: data.ocr?.extraDetails?.confidence_score,
            ocr_nationality: data.ocr?.nationality,
            ocr_address: data.ocr?.address,
            ocr_verified: data.ocr?.verified,
            version: data.version,
        }

        ApiSignals.dataSiganlKyc.value = {
            ...output,
        }

        return output
    },
    async insertKyc(payload: Kyc.Data.Insert) {
        const data: Parameters<typeof Apis.v1.refPostKyc>[0] = {
            country_code: payload.country_code,
            phone: payload.phone,
            first_name: payload.first_name,
            middle_name: payload.middle_name,
            last_name: payload.last_name,
            id_type: payload.id_type,
            id_number: payload.id_number,
            birthday: payload.birthday,
            nearest_branch: payload.nearest_branch,
            gender: payload.gender,
            attachments: {
                face: payload.attachments_face,
                idPhoto: payload.attachments_idPhoto,
                selfieWithIDPhotoPath: payload.attachments_selfieWithIDPhotoPath,
            },
            place_of_birth: payload.place_of_birth,
            nationality: payload.nationality,
            current_address: payload.current_address,
            permanent_address: payload.permanent_address,
            nature_of_work: payload.nature_of_work,
            source_of_income: payload.source_of_income,
            occupation: payload.occupation,
        }

        const response = await Apis.v1.refPostKyc(data)
        return response.data.data
    },
    async startOcrProcess(props: {
        iframe: boolean
        bizId: string
        idType: string
        callbackUrlSuccess: string
        callbackUrlFail: string
    }): Promise<Kyc.Data.OcrParams> {
        const response = await Apis.v1.refOcrSetup({
            is_frame: props.iframe,
            biz_id: props.bizId,
            id_type: props.idType,
            complete_callback_url: props.callbackUrlSuccess,
            interrupt_callback_url: props.callbackUrlFail,
        })

        const client_cfg: Kyc.Data.ClientCfg = parseOcrClientCfg(
            response.data.data?.client_cfg ?? "",
        )
        return {
            biz_id: response.data.data?.biz_id ?? "",
            client_cfg,
            redirect_url: response.data.data?.redirect_url ?? "",
            transaction_id: response.data.data?.transaction_id ?? "",
        }
    },
    async checkOcrResult(props: { transaction_id: string; biz_id: string; id_type: Kyc.IdType }) {
        const response = await Apis.v1.refOrcCheckResult({
            transaction_id: props.transaction_id,
            biz_id: props.biz_id,
            id_type: props.id_type,
        })

        return Boolean(response.data.status)
    },
    async submitKyc(payload: Kyc.Data.Insert) {
        const data: Parameters<typeof Apis.v1.refPostKyc>[0] = {
            attachments: {
                face: payload.attachments_face,
                idPhoto: payload.attachments_idPhoto,
                selfieWithIDPhotoPath: payload.attachments_selfieWithIDPhotoPath,
            },
            birthday: payload.birthday,
            blacklist_status: payload.blacklist_status,
            comment: payload.comment,
            country_code: payload.country_code,
            current_address: payload.current_address,
            first_name: payload.first_name,
            gender: payload.gender,
            id_number: payload.id_number,
            id_type: payload.id_type,
            last_name: payload.last_name,
            middle_name: payload.middle_name ?? "",
            nationality: payload.nationality,
            nature_of_work: payload.nature_of_work,
            nearest_branch: payload.nearest_branch,
            occupation: payload.occupation,
            permanent_address: payload.permanent_address,
            phone: payload.phone,
            place_of_birth: payload.place_of_birth,
            source_of_income: payload.source_of_income,
        }
        const response = await Apis.v1.refPostKyc(data)
        return response.data.data
    },
    async updateBasicInformation(
        payload: Pick<
            Kyc.Data.Update,
            "first_name" | "last_name" | "middle_name" | "birthday" | "gender"
        >,
    ) {
        const real_username = PayloadFormatter.jsonStringify({
            first_name: payload.first_name,
            middle_name: payload.middle_name,
            last_name: payload.last_name,
        })
        const data: Parameters<typeof Apis.v1.refUpdateDetail>[0] = {
            real_username,
            birthday: payload.birthday,
            gender: payload.gender,
        }
        return await this.refUpdateDetail({
            record: {
                ...data,
            },
        })
    },
    async updateKyc(payload: Kyc.Data.Update) {
        const data: Parameters<typeof Apis.v1.refUpdateKyc>[0] = {
            country_code: payload.country_code,
            phone: payload.phone,
            first_name: payload.first_name,
            middle_name: payload.middle_name,
            last_name: payload.last_name,
            id_type: payload.id_type,
            id_number: payload.id_number,
            birthday: payload.birthday,
            nearest_branch: payload.nearest_branch,
            gender: payload.gender,
            attachments: {
                face: payload.attachments_face,
                idPhoto: payload.attachments_idPhoto,
                selfieWithIDPhotoPath: payload.attachments_selfieWithIDPhotoPath,
            },
            place_of_birth: payload.place_of_birth,
            nationality: payload.nationality,
            current_address: payload.current_address,
            permanent_address: payload.permanent_address,
            nature_of_work: payload.nature_of_work,
            source_of_income: payload.source_of_income,
            occupation: payload.occupation,
        }
        const response = await Apis.v1.refUpdateKyc(data)
        return response.data.data
    },
    async refUploadFile(file: File): Promise<{
        object_key?: string
        signed_url?: string
    } | null> {
        const formData = new FormData()
        formData.append("file", file, file.name)
        const response = await fetch("/member/oss/upload", {
            method: "POST",
            body: formData,
            headers: {
                t: tokenStore.get().accessToken,
                lang: "en_US",
                d: "25",
            },
        })
        const decoded = cbor.decode(await response.arrayBuffer()) as {
            data:
                | {
                      object_key?: string
                      signed_url?: string
                  }
                | string
            status: boolean
        }
        if (decoded.status && typeof decoded.data === "object") {
            return decoded.data
        }
        throw ErrorFactory.createFileUploadError(decoded.data as string)
    },
}

ApiFetchers.refGetProfile = _.throttle(ApiFetchers.refGetProfile, 1500, {
    leading: true,
    trailing: false,
})
ApiFetchers.getKycV2 = _.throttle(ApiFetchers.getKycV2, 1500, {
    leading: true,
    trailing: false,
})

export default ApiFetchers
